﻿#region Using

using Commons.Diagnostics;
using SAPbouiCOM;
using SapFramework.Application;
using SapFramework.Extension.Interface;
using SapFramework.Interface.Events;


#endregion

namespace SapFramework.Interface.Controls.Forms.Base
{
    /// <summary>
    /// Realiza o encapsulamento de um objeto do tipo <see cref="SAPbouiCOM.Form"/> da UI API do SAP Business One.
    /// </summary>
    public abstract class Form : SAPbouiCOM.Form
    {
        #region Eventos

        /// <summary>
        /// Antes de um formulário ter sido aberto/carregado
        /// </summary>
        [Event( BoEventTypes.et_FORM_LOAD )]
        public event EventBoolItem OnBeforeFormLoad;

        /// <summary>
        /// Após um formulário ter sido ser aberto/carregado
        /// </summary>
        [Event( BoEventTypes.et_FORM_LOAD )]
        public event EventVoidItem OnAfterFormLoad;

        /// <summary>
        /// Antes de um formulário ter sido fechado/descarregado
        /// </summary>
        [Event( BoEventTypes.et_FORM_UNLOAD )]
        public event EventBoolItem OnBeforeFormUnload;

        /// <summary>
        /// Após um formulário ter sido aberto/carregado
        /// </summary>
        [Event( BoEventTypes.et_FORM_UNLOAD )]
        public event EventVoidItem OnAfterFormUnload;

        /// <summary>
        /// Antes de o formulário ter recebido o fóco
        /// </summary>
        [Event( BoEventTypes.et_FORM_ACTIVATE )]
        public event EventBoolItem OnBeforeFormActivate;

        /// <summary>
        /// Após o formulário ter recebido o fóco
        /// </summary>
        [Event( BoEventTypes.et_FORM_ACTIVATE )]
        public event EventVoidItem OnAfterFormActivate;

        /// <summary>
        /// Após o formulário ter perdido o fóco
        /// </summary>
        [Event( BoEventTypes.et_FORM_DEACTIVATE )]
        public event EventVoidItem OnFormDeactivate;

        /// <summary>
        /// Evento que ocorre antes de o formulário ser fechado.
        /// </summary>
        [Event( BoEventTypes.et_FORM_CLOSE )]
        public event EventBoolItem OnBeforeFormClose;

        /// <summary>
        /// Evento que ocorre após o formulário ser fechado.
        /// </summary>
        [Event( BoEventTypes.et_FORM_CLOSE )]
        public event EventVoidItem OnAfterFormClose;

        /// <summary>
        /// Após o formulário ter sido redimensionado
        /// </summary>
        [Event( BoEventTypes.et_FORM_RESIZE )]
        public event EventVoidItem OnFormResize;

        /// <summary>
        /// TODO: Testar!
        /// Uma tecla foi pressionada quando nenhum formulário estava focado. Antes da ação.
        /// </summary>
        [Event( BoEventTypes.et_FORM_KEY_DOWN )]
        public event EventBoolItem OnBeforeFormKeyDown;

        /// <summary>
        /// TODO: Testar!
        /// Uma tecla foi pressionada quando nenhum formulário estava focado. Depois da ação.
        /// </summary>
        [Event( BoEventTypes.et_FORM_KEY_DOWN )]
        public event EventVoidItem OnAfterFormKeyDown;

        /// <summary>
        /// Um formulário está tentando modificar o status de um item da barra de ferramentas, ou seja, ativando e/ou desativando icones nela.
        /// </summary>
        /// <remarks>
        /// Por padrão, estes eventos não são disparados. Pode-se ativa-los através da configuração de um filtro para eles.
        /// Como nossa Framework cria filtros para cada eventos registrado, acredito que não haverá problemas aqui, mas deixo o comentário para evitar problemas de pesquisa futuros.
        /// </remarks>
        [Event( BoEventTypes.et_FORM_MENU_HILIGHT )]
        public event EventVoidItem OnFormMenuHilight;

        /// <summary>
        /// Uma pré-visualização foi requisitada para um documento ou relatório. Disparado antes desta visualização ocorrer.
        /// </summary>
        /// <remarks>
        /// Este evento lhe permite evitar que a forma de impressão do SBO seja chamada, e lhe fornece os dados para que você realize sua própria visualização/impressão.
        /// </remarks>
        [Event( BoEventTypes.et_PRINT )]
        public event EventBoolPrint OnBeforePrint;

        /// <summary>
        /// Uma pré-visualização foi requisitada para um documento ou relatório. Disparado após a visualização ocorrer.
        /// </summary>
        [Event( BoEventTypes.et_PRINT )]
        public event EventVoidPrint OnAfterPrint;

        /// <summary>
        /// Uma pré-visualização foi requisitada para um relatório. Disparado antes da visualização ocorrer.
        /// </summary>
        /// <remarks>
        /// Este evento lhe permite recuperar os dados do relatório em formato XML.
        /// </remarks>
        [Event( BoEventTypes.et_PRINT_DATA )]
        public event EventBoolReportData OnBeforePrintData;

        /// <summary>
        /// Uma pré-visualização foi requisitada para um relatório. Disparado após a visualização ocorrer.
        /// </summary>
        /// <remarks>
        /// Este evento lhe permite recuperar os dados do relatório em formato XML.
        /// </remarks>
        [Event( BoEventTypes.et_PRINT_DATA )]
        public event EventVoidReportData OnAfterPrintData;

        /// <summary>
        /// Disparado antes da exibição do menu que ocorre quando um clique com o botão direito do mouse é feito sobre um item.
        /// </summary>
        [Event( BoEventTypes.et_RIGHT_CLICK )]
        public event EventBoolContextMenu OnBeforeRightClick;

        /// <summary>
        /// Disparado após a exibição do menu que ocorre quando um clique com o botão direito do mouse é feito sobre um item.
        /// </summary>
        [Event( BoEventTypes.et_RIGHT_CLICK )]
        public event EventVoidContextMenu OnAfterRightClick;

        /// <summary>
        /// Ocorre antes de um novo registro de objeto de negócio ser adicionado
        /// </summary>
        [Event( BoEventTypes.et_FORM_DATA_ADD )]
        public event EventBoolBusinessInfo OnBeforeFormDataAdd;

        /// <summary>
        /// Ocorre após um novo registro de objeto de negócio ser adicionado
        /// </summary>
        [Event( BoEventTypes.et_FORM_DATA_ADD )]
        public event EventVoidBusinessInfo OnAfterFormDataAdd;

        /// <summary>
        /// Ocorre antes de um registro de objeto de negócio ser excluido
        /// </summary>
        [Event( BoEventTypes.et_FORM_DATA_DELETE )]
        public event EventBoolBusinessInfo OnBeforeFormDataDelete;

        /// <summary>
        /// Ocorre após um registro de objeto de negócio ser excluido
        /// </summary>
        [Event( BoEventTypes.et_FORM_DATA_DELETE )]
        public event EventVoidBusinessInfo OnAfterFormDataDelete;

        /// <summary>
        /// Ocorre antes dos dados de um registro de objeto de negócio serem carregados.
        /// </summary>
        /// <remarks>
        /// A origem deste carregamento de dados pode ter sido a partir das setas de navegação no formulário, um Linked Button, ou um Find no formulário.
        /// </remarks>
        [Event( BoEventTypes.et_FORM_DATA_LOAD )]
        public event EventBoolBusinessInfo OnBeforeFormDataLoad;

        /// <summary>
        /// Ocorre após os dados de um registro de objeto de negócio serem carregados.
        /// </summary>
        /// <remarks>
        /// A origem deste carregamento de dados pode ter sido a partir das setas de navegação no formulário, um Linked Button, ou um Find no formulário.
        /// </remarks>
        [Event( BoEventTypes.et_FORM_DATA_LOAD )]
        public event EventVoidBusinessInfo OnAfterFormDataLoad;

        /// <summary>
        /// Ocorre antes dos dados de um registro de objeto de negócio serem atualizados.
        /// </summary>
        [Event( BoEventTypes.et_FORM_DATA_UPDATE )]
        public event EventBoolBusinessInfo OnBeforeFormDataUpdate;

        /// <summary>
        /// Ocorre após os dados de um registro de objeto de negócio serem atualizados.
        /// </summary>
        [Event( BoEventTypes.et_FORM_DATA_UPDATE )]
        public event EventVoidBusinessInfo OnAfterFormDataUpdate;

        #endregion

        internal AddOn AddOn { get; set; }

        /// <summary>
        /// Guarda uma referência ao formulário do SAP Business One, para realização do wrappe (encapsulamento).
        /// </summary>
        protected SAPbouiCOM.Form mForm;

        /// <summary>
        /// Mantém uma contagem da quantidade de vezes que o formulário foi congelado, para descogela-lo apenas quando a ultima chamada de UnFreeze for executada.
        /// </summary>
        private int mFreezeCounter = 0;

        /// <summary>
        /// Cria um novo formulário do PadaOne, baseado em um formulário recuperado do SAP Business One
        /// </summary>
        /// <param name="aAddOn">Referência para o <see cref="AddOn"/> que contém o <see cref="FormManager"/></param>
        /// <param name="aFormUniqueId">Id único para o objeto de formulário na SAP</param>
        public Form( AddOn aAddOn, string aFormUniqueId )
        {
            Contract.Requires.NotNull( () => aAddOn );
            Contract.Requires.NotNull( () => aAddOn.Forms );

            AddOn = aAddOn;

            Contract.Requires.NotNullOrEmpty( () => aFormUniqueId );

            mForm = aAddOn.Connection.Interface.Forms.Item( aFormUniqueId ); //è pra dar exceção mesmo se ele não existir aqui ainda...
            Items = new Items.Base.Items( this );
        }

        #region Implementation of IForm

        /// <summary>
        /// Método para acesso da coleção "Items" do SAP Business One
        /// </summary>
        SAPbouiCOM.Items IForm.Items
        {
            get { return mForm.Items; }
        }

        public void Select()
        {
            mForm.Select();
        }

        public void Close()
        {
            mForm.Close();
        }

        public void Refresh()
        {
            mForm.Refresh();
        }

        public string GetAsXML()
        {
            return mForm.GetAsXML();
        }

        public void Update()
        {
            mForm.Update();
        }

        void IForm.Freeze( bool newVal )
        {
            mForm.Freeze( newVal );
        }

        public FormFreeze Freezer()
        {
            return new FormFreeze( this );
        }

        /// <summary>
        /// Congela o formulário, caso ele ainda não tenha sido congelado.
        /// </summary>
        internal void Freeze()
        {
            if ( mFreezeCounter == 0 )
            {
                mForm.Freeze( true );
            }

            mFreezeCounter++;
        }

        /// <summary>
        /// Descongela o formulário, caso ainda não tenha sido descongelado.
        /// </summary>
        internal void UnFreeze()
        {
            mFreezeCounter = mFreezeCounter - 1 < 0 ? 0 : mFreezeCounter - 1;

            if ( mFreezeCounter == 0 )
            {
                mForm.Freeze( false );
            }
        }

        public void EnableMenu( string MenuUID, bool EnableFlag )
        {
            mForm.EnableMenu( MenuUID, EnableFlag );
        }

        public void ResetMenuStatus()
        {
            mForm.ResetMenuStatus();
        }

        public void Resize( int lWidth, int lHeight )
        {
            mForm.Resize( lWidth, lHeight );
        }

        public DataSource DataSources
        {
            get { return mForm.DataSources; }
        }

        public int TypeCount
        {
            get { return mForm.TypeCount; }
        }

        int IForm.Type
        {
            get { return mForm.Type; }
        }

        public bool Modal
        {
            get { return mForm.Modal; }
        }

        public bool Selected
        {
            get { return mForm.Selected; }
        }

        public string UniqueID
        {
            get { return mForm.UniqueID; }
        }

        public SAPbouiCOM.Menus Menu
        {
            get { return mForm.Menu; }
        }

        public BoFormBorderStyle BorderStyle
        {
            get { return mForm.BorderStyle; }
        }

        public string TypeEx
        {
            get { return mForm.TypeEx; }
        }

        public BusinessObject BusinessObject
        {
            get { return mForm.BusinessObject; }
        }

        public DataBrowser DataBrowser
        {
            get { return mForm.DataBrowser; }
        }

        public ChooseFromListCollection ChooseFromLists
        {
            get { return mForm.ChooseFromLists; }
        }

        public FormSettings Settings
        {
            get { return mForm.Settings; }
        }

        public bool IsSystem
        {
            get { return mForm.IsSystem; }
        }

        public string UDFFormUID
        {
            get { return mForm.UDFFormUID; }
        }

        public string ReportType
        {
            get { return mForm.ReportType; }
            set { mForm.ReportType = value; }
        }

        public string Title
        {
            get { return mForm.Title; }
            set { mForm.Title = value; }
        }

        public BoFormStateEnum State
        {
            get { return mForm.State; }
            set { mForm.State = value; }
        }

        public bool Visible
        {
            get { return mForm.Visible; }
            set { mForm.Visible = value; }
        }

        public string DefButton
        {
            get { return mForm.DefButton; }
            set { mForm.DefButton = value; }
        }

        public BoFormMode Mode
        {
            get { return mForm.Mode; }
            set { mForm.Mode = value; }
        }

        public int PaneLevel
        {
            get { return mForm.PaneLevel; }
            set { mForm.PaneLevel = value; }
        }

        public int Top
        {
            get { return mForm.Top; }
            set { mForm.Top = value; }
        }

        public int Left
        {
            get { return mForm.Left; }
            set { mForm.Left = value; }
        }

        public int Height
        {
            get { return mForm.Height; }
            set { mForm.Height = value; }
        }

        public int Width
        {
            get { return mForm.Width; }
            set { mForm.Width = value; }
        }

        public int ClientHeight
        {
            get { return mForm.ClientHeight; }
            set { mForm.ClientHeight = value; }
        }

        public int ClientWidth
        {
            get { return mForm.ClientWidth; }
            set { mForm.ClientWidth = value; }
        }

        public int SupportedModes
        {
            get { return mForm.SupportedModes; }
            set { mForm.SupportedModes = value; }
        }

        public bool AutoManaged
        {
            get { return mForm.AutoManaged; }
            set { mForm.AutoManaged = value; }
        }

        public string ActiveItem
        {
            get { return mForm.ActiveItem; }
            set { mForm.ActiveItem = value; }
        }

        #endregion

        /// <summary>
        /// Dicionário contendo os itens registrados deste formulário.
        /// </summary>
        public Items.Base.Items Items { get; private set; }

        /// <summary>
        /// Guarda uma "constante" para o tipo do formulário
        /// </summary>
        public string Type { get; private set; }
    }
}